/*********************************************************************************
 *      Copyright:  (C) 2022 dairongan<2974932606@qq.com>
 *                  All rights reserved.
 *
 *       Filename:  misc_api.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(07/31/2022)
 *         Author:  dairongan <2974932606@qq.com>
 *      ChangeLog:  1, Release initial version on "07/31/2022 12:04:15 PM"
 *                 
 ********************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <mosquitto.h>

#include "oled_api.h"
#include "beep.h"
#include "get_temp.h"
#include "logger.h"
#include "parse_mqttini.h"
#include "cJSON.h"
#include "misc_api.h"

void high_temp_warning(int fd_oled)
{
        OLED_ShowCHinese(fd_oled,91,4,6);               //高
        OLED_ShowCHinese(fd_oled,109,4,7);              //温
        OLED_ShowCHinese(fd_oled,91,6,8);               //警
        OLED_ShowCHinese(fd_oled,109,6,9);              //告
}

void high_temp_diswarning(int fd_oled)
{
        OLED_ShowCHinese(fd_oled,91,4,10);              //高
        OLED_ShowCHinese(fd_oled,109,4,10);             //温
        OLED_ShowCHinese(fd_oled,91,6,10);              //警
        OLED_ShowCHinese(fd_oled,109,6,10);             //告
}

void oled_show_temp_hum_chinese(int fd_oled)
{
        OLED_ShowCHinese(fd_oled,0,3,0);
        OLED_ShowCHinese(fd_oled,18,3,2);
        OLED_ShowString(fd_oled,36,3,":",16);
        OLED_ShowCHinese(fd_oled,0,6,1);
        OLED_ShowCHinese(fd_oled,18,6,2);
        OLED_ShowString(fd_oled,36,6,":",16);
}

void oled_show_temp_hum_num(int fd_oled,float temp_f,float hum_f)
{
        unsigned char buf[7];

        memset(buf,0,sizeof(buf));
        snprintf(buf,sizeof(buf),"%3.1f",temp_f);
        OLED_ShowString(fd_oled,44,3,buf,16);
        OLED_ShowCHinese(fd_oled,76,3,11);

        memset(buf,0,sizeof(buf));
        snprintf(buf,sizeof(buf),"%3.1f%%",hum_f);
        OLED_ShowString(fd_oled,44,6,buf,16);

}


int mqtt_connect(struct mosquitto *mosq,s_mosquitto_data *mqtt_data)
{
        int ret=0;

        if(!mosq || !mqtt_data)
        {
                log_error("The paremeter is NULL!\r\n");
                return -1;
        }

        ret=mosquitto_connect(mosq,mqtt_data->hostname,
                        mqtt_data->port,mqtt_data->keepalive);
        if(MOSQ_ERR_SUCCESS!=ret)
        {
                log_debug("connect mqtt server failed! :%s\r\n",mosquitto_strerror(ret));
                return ret;
        }

        ret=mosquitto_loop_start(mosq);
        if(MOSQ_ERR_SUCCESS!=ret)
        {
                log_debug("mosquitto loop failed! :%s\r\n",mosquitto_strerror(ret));
                goto Cleanup_loop_stop;
        }
        log_info("connect mqtt server successfully!\r\n");

        return MOSQ_ERR_SUCCESS;
Cleanup_loop_stop:
        mosquitto_loop_stop(mosq,true);
        return ret;

}

int publish_message(struct mosquitto *mosq,s_mosquitto_data *mqtt_data,char *databuf)
{
        int ret=0;
        int mid=0;

        ret=mosquitto_publish(mosq,&mid,mqtt_data->pub_topic,strlen(databuf)+1,
                        databuf,0,true);
        if(MOSQ_ERR_SUCCESS!=ret)
        {
                log_error("mosquitto publish_temp_hum failed! :%s\r\n",mosquitto_strerror(ret));
                ret=mosquitto_loop_stop(mosq,true);
                if(ret!=MOSQ_ERR_SUCCESS)
                {
                        log_error("mosquitto loop stop failed! :%s\r\n",mosquitto_strerror(ret));
                        return ret;
                }
                return ret;
        }
        log_info("data published successfully!\r\n");

        return MOSQ_ERR_SUCCESS;

}

int subscribe_message(struct mosquitto *mosq,s_mosquitto_data *mqtt_data)
{
        int ret=0;
        int mid=0;

        ret=mosquitto_subscribe(mosq,&mid,mqtt_data->sub_topic,0);
        if(MOSQ_ERR_SUCCESS!=ret)
        {
                ret=mosquitto_loop_stop(mosq,true);
                if(ret!=MOSQ_ERR_SUCCESS)
                {
                        log_error("mosquitto loop stop failed! :%s\r\n",strerror(errno));
                        return ret;
                }
                return ret;
        }
        log_info("data subscribe successfully!\r\n");
        return MOSQ_ERR_SUCCESS;
}
int pack_temp_hum(char *databuf,int size,float temp_f,float hum_f)
{
        if(!databuf)
        {
                log_error("The paremeter is NULL!\r\n");
                return -1;
        }

        struct tm *timer;
        timer=get_time();

        memset(databuf,0,size);
#if 1
        snprintf(databuf,size,"{\"Temperature\":\"%.2f\",\"Humidity\":\"%.2f\"}",
                                                        temp_f,hum_f);
#endif
#if 0
        snprintf(databuf,size,"{\"time\":\"%04d-%02d-%02d %02d:%02d:%02d\"," \
                                                        "\"Temperature\":\"%.2f\"," \
                                                        "\"Humidity\":\"%.2f\"}",
                                                        timer->tm_year+1900,timer->tm_mon+1,timer->tm_mday,
                                                        timer->tm_hour+8,timer->tm_min,timer->tm_sec,
                                                        temp_f,hum_f);
#endif
        log_info("%s\r\n",databuf);
        return 0;
}


//设置为void类型是因为即使失败也要继续执行后面的动作
void check_temp_limit(int fd_oled,float temp_f)
{
        int ret=0;
        static int beep_flag=beep_off;

        if(temp_f>TEMP_LIMIT)
        {
                if(beep_flag==beep_off)
                {
                        high_temp_warning(fd_oled);                     //高温警告显示
                        ret=beep_open();                                        //打开蜂鸣器报警
                        if(ret!=0)
                        {
                                log_error("open beep failure!\r\n");
                                beep_close();
                        }
                        beep_flag=beep_on;
                }
        }
        else
        {
                if(beep_flag==beep_on)
                {
                        beep_close();
                        high_temp_diswarning(fd_oled);          //关闭高温警告显示
                        beep_flag=beep_off;
                }
        }
}

void dra_message_callback(struct mosquitto *mosq, void *obj, const struct mosquitto_message *msg)
{
        int ret=0;

        if(msg->payload)
        {
                log_info("subscribe message is :%s\r\n",msg->payload);
        }
        ret=parse_sub_json(msg->payload);
        if(0==ret)
        {
                log_info("parse subscribe message successfully!\r\n");
        }
        else
        {
                log_error("parse subscribe message failed!\r\n");
        }
}

int parse_sub_json(void *message)
{
        int ret=0;
        int fd=0;
        unsigned char cmd[1];

        cJSON *item = NULL;
        cJSON *json = NULL;

    if( !message )
    {
        log_error( "Invalid input arguments!\n" );
        return -1;
    }

        json = cJSON_CreateObject();
        json = cJSON_Parse( message );

        //判断接收到的是否为RedLed
        if(cJSON_HasObjectItem(json,"RedLed"))
        {
                item=cJSON_GetObjectItem( json, "RedLed" );
                printf("item->valuestring:%s\r\n",item->valuestring);

                fd=open("/dev/my-leds",O_RDWR);
                if(fd<0)
                {
                        log_error("file %s open failure!\r\n","/dev/my-leds");
                        goto Cleanup_cjson;
                }

                if(0==strncmp(item->valuestring,"on",2))
                {
                        cmd[0]=3;
                }else if(0==strncmp(item->valuestring,"off",3))
                {
                        cmd[0]=2;
                }
                else
                {
                        log_error("The message dose not match control command!\r\n");
                        goto Cleanup_cjson;
                }

                ret=write(fd,cmd,1);
                if(ret<0)
                {
                        log_error("write led failed!\r\n");
                        goto Cleanup_cjson;
                }

                log_info("control light successfully!\r\n");
        }
        else
        {
                log_error("the light not exist!\r\n");
        }
Cleanup_cjson:
        close(fd);
        cJSON_Delete(json);

        return ret;
}

int oled_open()
{
	int fd_oled;
	//打开oled设备文件
    fd_oled = open(OLED_PATH, O_RDWR);
	return fd_oled;
}

void oled_close(int fd)
{
	close(fd);
}
